package com.ruike.alisurface.Serials;

import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;

import com.ruike.alisurface.BuildConfig;
import com.ruike.alisurface.utils.MyCountDownTimer;
import com.ruike.alisurface.utils.SerialsVerify;
import com.voodoo.lib_utils.ByteUtils;
import com.voodoo.lib_utils.L;

import java.math.BigInteger;

public class ICCardUtils {

    private static final String TAG = "ICCardUtils";

    private static MyCountDownTimer getCardPwdCountDownTimer;
    private static boolean isPolling = false; // 是否开始轮询
    private static boolean isReadCardNumber = false;

    public static void initListener() {
        Ttys1Utils.getInstance().setOnSerialPortResultDataListener(new Ttys1Utils.OnSerialPortResultDataListener() {
            @Override
            public void onDataReceived(String resultDataStr, byte[] resultBytes) {
                Handler mainHandler = new Handler(Looper.getMainLooper());
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (resultBytes[0] == (byte) 0xAA && resultBytes[1] == (byte) 0xBB && resultBytes.length > 9) {
                            byte resultByte = resultBytes[8];
                            switch (resultByte) {
                                case 0x00: // 操作成功
                                    mySerialPortResultData(resultDataStr, resultBytes);
                                    break;
                                case 0x0A: // 通用错误
                                    errorFengMing();
                                    L.eTag(TAG, "通用错误：" + resultDataStr);
                                    if (onICCardGetPwdListener != null) {
                                        onICCardGetPwdListener.onResultCardPwd("刷卡异常，请重新进入刷卡界面");
                                    }
                                    break;
                                case 0x0B: // 不支持该命令
                                    errorFengMing();
                                    L.eTag(TAG, "不支持该命令：" + resultDataStr);
                                    if (onICCardGetPwdListener != null) {
                                        onICCardGetPwdListener.onResultCardPwd("遇到不支持的命令");
                                    }
                                    break;
                                case 0x0C: // 命令参数错
                                    errorFengMing();
                                    L.eTag(TAG, "命令参数错：" + resultDataStr);
                                    if (onICCardGetPwdListener != null) {
                                        onICCardGetPwdListener.onResultCardPwd("命令参数出错，请重试或联系管理员");
                                    }
                                    break;
                                case 0x0D: // 无卡
                                    L.eTag(TAG, "无卡：" + resultDataStr);
                                    break;
                                case 0x0E: // 射频基站损坏
                                    errorFengMing();
                                    L.eTag(TAG, "射频基站损坏：" + resultDataStr);
                                    if (onICCardGetPwdListener != null) {
                                        onICCardGetPwdListener.onResultCardPwd("射频基站损坏，请联系管理员");
                                    }
                                    break;
                                case 0x14: // 寻卡失败
                                    L.eTag(TAG, "寻卡失败：" + resultDataStr);
                                    break;
                                case 0x15: // 卡复位失败
                                    L.eTag(TAG, "卡复位失败：" + resultDataStr);
                                    break;
                                case 0x16: // 密码验证失败
                                    L.eTag(TAG, "密码验证失败：" + resultDataStr);
                                    break;
                                case 0x17: // 读卡失败
                                    L.eTag(TAG, "读卡失败：" + resultDataStr);
                                    break;
                                case 0x18: // 写卡失败
                                    L.eTag(TAG, "写卡失败：" + resultDataStr);
                                    break;
                            }
                        } else if (isReadCardNumber) {
                            StringBuilder stringBuilder = new StringBuilder();
                            int lenth = resultBytes.length > 4 ? 10 : resultBytes.length;
                            for (int i = 0; i < lenth; i++) {
                                stringBuilder.append((char) (resultBytes[i]));
                            }
                            if (onICCardGetPwdListener != null) {
                                L.iTag(TAG, "获取到的卡号：" + stringBuilder.toString());
                                onICCardGetPwdListener.onResultCardPwd("获取到的卡号：" + stringBuilder.toString());
                                isReadCardNumber = false;
                            }
                        } else {
                            L.eTag(TAG, "返回数据头信息异常：" + resultDataStr);
                        }
                    }
                });
            }
        });
    }

    private static void mySerialPortResultData(String serialPortData, byte[] resultBytes) {

        L.iTag(TAG, "接收刷卡数据: ", serialPortData);

        // 获取块区返回的数据
        if (resultBytes[6] == 0x08 && resultBytes[7] == 0x06) {
            if (resultBytes.length < 26) {
                L.eTag(TAG, "获取卡密码返回值长度异常，无法解析。" + serialPortData);
                errorFengMing();
                return;
            }
            isPolling = false;
            stopGetCard();
            if (!BuildConfig.DEBUG) {
                fengMing();
            }
            String[] resultStrings = serialPortData.split(" ");
            StringBuffer pwdStringBuffer = new StringBuffer();
            int i = 9;
            for (; i < resultStrings.length - 1; i++) {
                pwdStringBuffer.append(resultStrings[i]);
                if (resultStrings[i].equals("AA") && resultStrings[i + 1].equals("00")) {
                    i++;
                }
            }
            if (onICCardGetPwdListener != null) {
                L.iTag(TAG, "获取到的卡块区数据：" + pwdStringBuffer.toString());
                onICCardGetPwdListener.onResultCardPwd(pwdStringBuffer.toString());
            }
        }

    }

    public static OnICCardGetPwdListener onICCardGetPwdListener;

    public static void setOnICCardGetPwdListener(OnICCardGetPwdListener onICCardGetPwdListener) {
        ICCardUtils.onICCardGetPwdListener = onICCardGetPwdListener;
    }

    /**
     * 获取卡密码监听
     */
    public interface OnICCardGetPwdListener {
        /**
         * 块区数据
         *
         * @param cardBlocksData 解析出来之后的数据
         */
        void onResultCardPwd(String cardBlocksData);

        /**
         * 刷卡返回异常
         *
         * @param errorMsg 异常信息
         */
        void onCreditCardError(String errorMsg);
    }

    // ==================================== M系列读卡器通讯协议 ====================================

    /**
     * 读写模式(在开机的时候使用)
     * <p>
     * 发送：AA BB 06 00 00 00 01 06 '01' 06 ----- 01进入读写模块（被动读写卡，由指令控制）  01  04
     * 返回：AA BB 06 00 00 00 01 06 00 07
     * <p>
     */
    public static void readWriteMode(boolean isZiDong) {
        byte[] strSerialComSend = new byte[10];
        strSerialComSend[0] = (byte) 0xAA;
        strSerialComSend[1] = (byte) 0xBB;
        strSerialComSend[2] = 0x06;
        strSerialComSend[3] = 0x00;
        strSerialComSend[4] = 0x00;
        strSerialComSend[5] = 0x00;
        strSerialComSend[6] = 0x01;
        strSerialComSend[7] = 0x06;
        strSerialComSend[8] = (byte) (isZiDong ? 4 : 1);
        strSerialComSend[9] = (byte) Integer.parseInt(SerialsVerify.getBCC(strSerialComSend, 4), 16);
        L.iTag(TAG, "发送读写模式指令：" + ByteUtils.byteArrToHex(strSerialComSend) + " ---- 自动读取:" + isZiDong);
        Ttys1Utils.getInstance().SendPort(ByteUtils.byteArrToHex(strSerialComSend));
    }

    /**
     * 寻卡密码
     */
    public static void getCardPwd(long countDownTimeMillis) {
        isPolling = true;
        if (getCardPwdCountDownTimer != null) {
            getCardPwdCountDownTimer.cancel();
        }
        getCardPwdCountDownTimer = new MyCountDownTimer(countDownTimeMillis, 1_000) {
            @Override
            public void onTick(long millisUntilFinished) {
                if (isPolling) {
                    // 发送：AA BB 0D 00 00 00 08 06 60 '01' 'FF FF FF FF FF FF' 6F ----- 01为块号；FF FF FF FF FF FF为密码
                    // 返回：AA BB 16 00 00 00 08 06 00 11 22 33 44 55 66 77 88 99 00 AA 00 BB CC DD EE FF 0E ----- 备注：数据有AA的，后面会多发一个00
                    getBlocksData(25);
                }
            }

            @Override
            public void onFinish() {
                stopGetCard();
            }
        };
        getCardPwdCountDownTimer.start();
    }

    /**
     * 防冲突读卡号  AA BB 06 00 00 00 02 02 04 04
     */
    public static void getCardNumber() {
        isPolling = true;
        isReadCardNumber = true;
        readCardNumber();
    }

    /**
     * 读取块区内容
     * <p>
     * 发送：AA BB 0D 00 00 00 08 06 60 '01' 'FF FF FF FF FF FF' 6F ----- 01为块号；FF FF FF FF FF FF为密码
     * 返回：AA BB 16 00 00 00 08 06 00 11 22 33 44 55 66 77 88 99 00 AA 00 BB CC DD EE FF 0E ----- 备注：数据有AA的，后面会多发一个00
     * <p>
     *
     * @param blockNumber 块号
     */
    private static void getBlocksData(int blockNumber) {
        byte[] strSerialComSend = new byte[17];
        strSerialComSend[0] = (byte) 0xAA;
        strSerialComSend[1] = (byte) 0xBB;
        strSerialComSend[2] = 0x0D;
        strSerialComSend[3] = 0x00;
        strSerialComSend[4] = 0x00;
        strSerialComSend[5] = 0x00;
        strSerialComSend[6] = 0x08;
        strSerialComSend[7] = 0x06;
        strSerialComSend[8] = 0x60;
        strSerialComSend[9] = (byte) blockNumber;
        strSerialComSend[10] = (byte) 0xFF;
        strSerialComSend[11] = (byte) 0xFF;
        strSerialComSend[12] = (byte) 0xFF;
        strSerialComSend[13] = (byte) 0xFF;
        strSerialComSend[14] = (byte) 0xFF;
        strSerialComSend[15] = (byte) 0xFF;
        strSerialComSend[16] = (byte) Integer.parseInt(SerialsVerify.getBCC(strSerialComSend, 4), 16);
        L.iTag(TAG, "发送一键读卡操作指令：" + ByteUtils.byteArrToHex(strSerialComSend) + " ---- 块号:" + blockNumber);
        Ttys1Utils.getInstance().SendPort(ByteUtils.byteArrToHex(strSerialComSend));
    }

    /**
     * 读取卡号
     */
    private static void readCardNumber() {
        byte[] strSerialComSend = new byte[10];
        strSerialComSend[0] = (byte) 0xAA;
        strSerialComSend[1] = (byte) 0xBB;
        strSerialComSend[2] = 0x06;
        strSerialComSend[3] = 0x00;
        strSerialComSend[4] = 0x00;
        strSerialComSend[5] = 0x00;
        strSerialComSend[6] = 0x01;
        strSerialComSend[7] = 0x06;
        strSerialComSend[8] = 0x02; // 09
        strSerialComSend[9] = 0x05; // 0E
        L.iTag(TAG, "只读模式1：" + ByteUtils.byteArrToHex(strSerialComSend));
        Ttys1Utils.getInstance().SendPort(ByteUtils.byteArrToHex(strSerialComSend));
    }

    /**
     * 蜂鸣鸣响
     * <p>
     * 发送：AA BB 06 00 00 00 06 01 '01' 06 (单引号中01为蜂鸣时间，1----10范围)
     * 返回：AA BB 06 00 00 00 06 01 00 07
     * <p>
     */
    private static void fengMing() {
        Ttys1Utils.getInstance().SendPort("AA BB 06 00 00 00 06 01 01 06");
    }

    /**
     * 产生异常的蜂鸣三声
     */
    private static void errorFengMing() {
        fengMing();
        SystemClock.sleep(200);
        fengMing();
        SystemClock.sleep(200);
        fengMing();
    }

    /**
     * 停止轮询计时
     */
    public static void stopGetCard() {
        isPolling = false;
        if (getCardPwdCountDownTimer != null) {
            L.iTag(TAG, "停止寻卡密码，取消计时器。");
            getCardPwdCountDownTimer.cancel();
            getCardPwdCountDownTimer = null;
        }
    }

}
